package com.loyi.ams.gateway.hbmis.rest;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.configuration.VFSFileSystem;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.NameScope;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.provider.ftp.FtpFileSystemConfigBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.loyi.ams.gateway.hbmis.config.HbmisConfigProperties;
import com.loyi.ams.gateway.hbmis.dao.IDeviceDAO;
import com.loyi.ams.gateway.hbmis.dao.IPictureDataDAO;
import com.loyi.cloud.hbmis.api.IDeviceService;
import com.loyi.cloud.hbmis.api.IPictureDataService;
import com.loyi.cloud.hbmis.domain.Device;
import com.loyi.cloud.hbmis.domain.PictureArgs;
import com.loyi.cloud.hbmis.domain.PictureData;
import com.netflix.discovery.converters.Auto;

@RestController
@RequestMapping("picture")
public class PictureDataService implements IPictureDataService {

	@Autowired
	private IPictureDataDAO pictureDataDAO;

	@Autowired
	private IDeviceService deviceService;

	@Autowired
	private HbmisConfigProperties hbmisConfigProperties;

	@Autowired(required = false)
	private FileSystemOptions fileSystemOptions;

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private FileSystemOptions fileSystemOptions() {
		FileSystemOptions opts = new FileSystemOptions();
		// FtpFileSystemConfigBuilder.getInstance().set
		return opts;
	}

	private String fomartPath(Date datatime) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datatime);
		return String.format("%s%s%s%s%s%s%s", calendar.get(Calendar.YEAR), File.separator,
				calendar.get(Calendar.MONTH) + 1, File.separator, calendar.get(Calendar.DAY_OF_MONTH), File.separator,
				calendar.get(Calendar.HOUR_OF_DAY));
	}

	@RequestMapping(value = "save", method = { RequestMethod.POST })
	public void save(@RequestBody PictureData data) {

		// File dir, thumbDir, cameraDir, file;

		FileObject dir, thumbDir = null, cameraDir = null, file;
		PictureData exitData = null;
		OutputStream fos = null;

		List<Device> devices;
		FileSystemOptions opts;
		
		logger.info("请求保存图片"+data.getBinarydata());

		opts = this.fileSystemOptions;
		if (opts == null) {
			opts = this.defaultFileSystemOptions();
		}

		try {
			dir = VFS.getManager().resolveFile(hbmisConfigProperties.getDataPath(), opts);
			if (!dir.exists()) {
				dir.createFolder();
			}
		} catch (FileSystemException e1) {
			throw new RuntimeException(
					String.format("访问文件夹[%s]失败，请检查配置是否正确,错误原因：%s", this.hbmisConfigProperties.getDataPath(),e1.getMessage()));
		}
		// 保存图片
		try {

			thumbDir = dir.resolveFile("thumb");
			if (!thumbDir.exists()) {
				thumbDir.createFolder();
			}
			thumbDir = thumbDir.resolveFile(fomartPath(new Date(data.getDatatime())),NameScope.FILE_SYSTEM);
			

			cameraDir = dir.resolveFile("camera");			
			if (!cameraDir.exists()) {
				cameraDir.createFolder();
			}
			cameraDir = cameraDir.resolveFile(fomartPath(new Date(data.getDatatime())),NameScope.FILE_SYSTEM);
		} catch (FileSystemException ex) {
			throw new RuntimeException(String.format("读取图片存储目录失败，错误原因:%s", ex.getMessage()));
		}

		try {
			file = cameraDir.resolveFile(data.getBinarydata(),NameScope.FILE_SYSTEM);
			if (!file.exists()) {
				file.createFile();
			}
			fos = file.getContent().getOutputStream();
			IOUtils.write(data.getData(), fos);
		} catch (Exception e) {
			throw new RuntimeException("写入图片文件失败", e);
		} finally {
			IOUtils.closeQuietly(fos);
		}

		try {
			file = thumbDir.resolveFile(data.getBinarydata(),NameScope.FILE_SYSTEM);
			if (!file.exists()) {
				file.createFile();
			}
			fos = file.getContent().getOutputStream();
			IOUtils.write(data.getThumbData(), fos);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("写入图片文件失败", e);
		} finally {
			IOUtils.closeQuietly(fos);
		}

		// 通过设备编号查找监测点编号
		devices = deviceService.find(null, data.getDeviceid(), null, Arrays.asList(2));
		// devices.
		if (devices == null || devices.size() == 0) {
			logger.warn(String.format("无法找到对应监测点位,设备编号：%s", data.getDeviceid()));
			return;
		}
		data.setPtid(devices.get(0).getPtid());

		exitData = pictureDataDAO.find(data.getDatatime(), data.getPtid());
		if (exitData == null) {
			pictureDataDAO.insert(data);
		} else {
			data.setPicid(exitData.getPicid());
			pictureDataDAO.update(data);
		}		
		
		logger.info("图片保存成功:"+data.getBinarydata());

	}

	@Override
	@RequestMapping(value = "findAll", method = { RequestMethod.GET })
	public List<PictureData> findAll(@RequestParam("ptid") String ptid,
			@DateTimeFormat(pattern = "yyyyMMddHHmmss") @RequestParam("starttime") Date starttime,
			@DateTimeFormat(pattern = "yyyyMMddHHmmss") @RequestParam("endtime") Date endtime) {
		return this.pictureDataDAO.findAll(ptid, starttime.getTime(), endtime.getTime());
	}

	@Override
	@RequestMapping(value = "thumb", method = { RequestMethod.GET }, produces = { "image/jpeg" })
	public byte[] thumb(@RequestParam("datatime") @DateTimeFormat(pattern = "yyyyMMddHHmmss") Date datatime,
			@RequestParam("fileName") String fileName) {
		FileObject dir, fo;
		InputStream is = null;
		byte[] defaultValue = new byte[0];
		FileSystemOptions opts;

		opts = this.fileSystemOptions;
		if (opts == null) {
			opts = this.defaultFileSystemOptions();
		}
		try {
			dir = VFS.getManager().resolveFile(hbmisConfigProperties.getDataPath(), opts);
			if (!dir.exists()) {
				logger.warn("目录不存在" + dir);
				return defaultValue;
			}
			dir = dir.resolveFile("thumb");
			dir = dir.resolveFile(this.fomartPath(datatime),NameScope.FILE_SYSTEM);
			if (!dir.exists()) {
				logger.warn("目录不存在" + dir);
				return defaultValue;
			}
			fo = dir.resolveFile(fileName);
			if (!fo.exists()) {
				return defaultValue;
			}
			is = fo.getContent().getInputStream();
			return IOUtils.toByteArray(is);
		} catch (FileSystemException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (is != null) {
				IOUtils.closeQuietly(is);
			}
		}
		return defaultValue;
	}

	@Override
	@RequestMapping(value = "camera", method = { RequestMethod.GET }, produces = { "image/jpeg" })
	public byte[] camera(@RequestParam("datatime") @DateTimeFormat(pattern = "yyyyMMddHHmmss") Date datatime,
			@RequestParam("fileName") String fileName) {
		FileObject dir, fo;
		InputStream is = null;
		byte[] defaultValue = new byte[0];
		FileSystemOptions opts;

		opts = this.fileSystemOptions;
		if (opts == null) {
			opts = this.defaultFileSystemOptions();
		}
		try {
			dir = VFS.getManager().resolveFile(hbmisConfigProperties.getDataPath(), opts);
			if (!dir.exists()) {
				logger.debug("目录不存在" + dir);
				return defaultValue;
			}
			dir = dir.resolveFile("camera");
			dir = dir.resolveFile(this.fomartPath(datatime),NameScope.FILE_SYSTEM);
			if (!dir.exists()) {
				logger.debug("目录不存在" + dir);
				return defaultValue;
			}
			fo = dir.resolveFile(fileName);
			if (!fo.exists()) {
				return defaultValue;
			}
			is = fo.getContent().getInputStream();
			return IOUtils.toByteArray(is);
		} catch (FileSystemException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (is != null) {
				IOUtils.closeQuietly(is);
			}
		}
		return defaultValue;
	}

	private FileSystemOptions defaultFileSystemOptions() {
		FileSystemOptions opts = new FileSystemOptions();
		FtpFileSystemConfigBuilder.getInstance().setConnectTimeout(opts, 5000);
		FtpFileSystemConfigBuilder.getInstance().setControlEncoding(opts, "utf-8");
		FtpFileSystemConfigBuilder.getInstance().setEntryParser(opts, "Unix");
		FtpFileSystemConfigBuilder.getInstance().setSoTimeout(opts, 5000);
		FtpFileSystemConfigBuilder.getInstance().setPassiveMode(opts, true);
		return opts;
	}

}
